package com.zdpx.pxframework.system.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zdpx.pxframework.core.exception.GlobalException;
import com.zdpx.pxframework.core.vo.CodeMsg;
import com.zdpx.pxframework.system.api.entity.UserInfo;
import com.zdpx.pxframework.system.entity.MenuInfo;
import com.zdpx.pxframework.system.mapper.MenuInfoMapper;
import com.zdpx.pxframework.system.service.AdminService;
import com.zdpx.pxframework.system.service.MenuInfoService;
import com.zdpx.pxframework.system.service.UserInfoService;
import com.zdpx.pxframework.system.vo.codemsg.SystemCodeMsg;
import com.zdpx.pxframework.system.vo.vo.MenuInfoTreeVo;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;


/**
 * 菜单信息 服务实现类
 *
 * @Description:
 * @Author: Cheng XiaoXiao
 * @Date: 2022-02-27 15:20:14
 */
@Service
public class MenuInfoServiceImpl extends ServiceImpl<MenuInfoMapper, MenuInfo> implements MenuInfoService {

    @Resource
    UserInfoService userInfoService;
    @Resource
    AdminService adminService;

    /**
     * 顶级菜单ID
     */
    public static final String TOP_PARENT_ID = "0";

    /**
     * 获取菜单详情
     *
     * @param id ID
     * @return 单个菜单详情
     */
    @Override
    public MenuInfo detailById(String id) {
        return this.getById(id);
    }

    /**
     * 增加菜单信息
     *
     * @param menuInfo 菜单对象
     */
    @Override
    public void saveMenuInfo(MenuInfo menuInfo) {
        //菜单标识必须唯一
        MenuInfo oldMenuInfo = this.getOneByMenuKey(menuInfo.getMenuKey());
        if (oldMenuInfo != null) {
            throw new GlobalException(SystemCodeMsg.MENU_KEY_EXIST);
        }

        //父节点未输入默认为0
        if (StringUtils.isBlank(menuInfo.getParentId())) {
            menuInfo.setParentId(TOP_PARENT_ID);
        }

        //自动生成级别信息
        if (TOP_PARENT_ID.equals(menuInfo.getParentId())) {
            menuInfo.setLevel(1);
        } else {
            MenuInfo parentInfo = this.getById(menuInfo.getParentId());
            if (parentInfo == null) {
                throw new GlobalException(SystemCodeMsg.PARENT_MENU_NOT_EXIST);
            }
            menuInfo.setLevel(parentInfo.getLevel() + 1);
        }


        this.baseMapper.insert(menuInfo);
    }

    /**
     * 修改菜单信息
     *
     * @param menuInfo 菜单对象
     */
    @Override
    public void updateMenuInfoById(MenuInfo menuInfo) {
        //菜单标识必须唯一
        MenuInfo oldMenuInfo = this.getOneByMenuKey(menuInfo.getMenuKey());
        if (oldMenuInfo != null && !oldMenuInfo.getId().equals(menuInfo.getId())) {
            throw new GlobalException(SystemCodeMsg.MENU_KEY_EXIST);
        }

        this.baseMapper.updateById(menuInfo);
    }

    /**
     * 根据ID删除
     *
     * @param id ID
     */
    @Override
    public void deleteById(String id) {
        this.removeById(id);
    }


    /**
     * 递归处理获取子节点
     *
     * @param menuInfo    当前树节点
     * @param allMenuInfo 所有的树节点
     * @return 包含子节点的树结构
     */
    private MenuInfoTreeVo treeSelectChildren(MenuInfo menuInfo, List<MenuInfo> allMenuInfo) {
        MenuInfoTreeVo menuInfoTreeVo = new MenuInfoTreeVo();
        BeanUtil.copyProperties(menuInfo, menuInfoTreeVo);

        if (menuInfoTreeVo.getChildren() == null) {
            menuInfoTreeVo.setChildren(new ArrayList<>());
        }

        for (MenuInfo item : allMenuInfo) {
            if (item.getParentId().equals(menuInfo.getId())) {
                menuInfoTreeVo.getChildren().add(treeSelectChildren(item, allMenuInfo));
            }
        }
        return menuInfoTreeVo;
    }

    /**
     * 查询菜单树形结构
     *
     * @return 菜单树形结构
     */
    @Override
    public List<MenuInfoTreeVo> tree() {
        List<MenuInfo> allMenuInfo = this.list(new QueryWrapper<MenuInfo>().orderByAsc("id"));

        List<MenuInfoTreeVo> list = new ArrayList<>();

        //进行递归查询，封装成树结构
        for (MenuInfo menuInfo : allMenuInfo) {
            if ("0".equals(menuInfo.getParentId())) {
                //存在多个一级节点
                list.add(treeSelectChildren(menuInfo, allMenuInfo));
            }
        }

        return list;
    }

    /**
     * 根据菜单标识获取菜单信息
     *
     * @param menuKey 菜单标识
     * @return 菜单信息
     */
    @Override
    public MenuInfo getOneByMenuKey(String menuKey) {
        return this.getOne(new LambdaQueryWrapper<MenuInfo>().eq(MenuInfo::getMenuKey, menuKey));
    }

    /**
     * 根据用户ID获取菜单标识列表
     *
     * @param userId 用户ID
     * @return 菜单标识列表
     */
    @Override
    public Set<String> getMenuKeysByUserId(String userId) {
        UserInfo userInfo = userInfoService.getById(userId);
        if (userInfo == null) {
            throw new GlobalException(CodeMsg.USER_NOT_EXIST);
        }
        if (adminService.isAdmin(userInfo)) {
            return adminService.getAllMenuKeys();
        } else {
            return this.baseMapper.selectPermissionKeyListByUserId(userId);
        }
    }
}
